﻿#region using statements

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using XNAGameEngine.Utility;

#endregion

namespace XNAGameEngine.Input
{
    public sealed partial class ManagerInput
    {
        #region Nested type: ManagerMouseInput

        private sealed class ManagerMouseInput
        {
            #region local fields

            /// <summary>
            /// reference to the input manager
            /// </summary>
            private readonly ManagerInput _inputManager;

            /// <summary>
            /// Stores the value of the mouse position whenever the mouse is moved
            /// </summary>
            private Vector2 _mouseValue;

            #endregion

            #region properties

            /// <summary>
            /// Get the current state of the mouse
            /// </summary>
            private MouseState _CurrentMouseState { get; set; }

            /// <summary>
            /// Get the last state of the mouse
            /// </summary>
            private MouseState _LastMouseState { get; set; }

            #endregion

            #region constructors

            /// <summary>
            /// Default constructor, saves a reference to the input manager
            /// </summary>
            /// <param name="inputManager">the input manager that creates this object</param>
            public ManagerMouseInput(ManagerInput inputManager)
            {
                _inputManager = inputManager;
            }

            #endregion

            #region local methods

            /// <summary>
            /// Updates the mouse and throws the input events
            /// </summary>
            /// <param name="gameTime">the game time object</param>
            public void Update(GameTime gameTime)
            {
                _CurrentMouseState = Mouse.GetState();

                // For every key on the keyboard
                foreach (
                    MouseClick input in EnumParse.GetEnumValues<MouseClick>())
                {
                    // If it is a new key press throw the key pressed event
                    if (WasButtonPressed(input))
                    {
                        switch (input)
                        {
                            case MouseClick.MOVE:
                                _mouseValue.X = _CurrentMouseState.X;
                                _mouseValue.Y = _CurrentMouseState.Y;
                                _inputManager.InputPressed(
                                    null, null, input, null, _mouseValue);
                                break;
                            case MouseClick.SCROLL:
                                _inputManager.InputPressed(
                                    null, null, input,
                                    (_CurrentMouseState.ScrollWheelValue -
                                     _LastMouseState.ScrollWheelValue) / 120,
                                    _mouseValue);
                                break;
                            default:
                                _inputManager.InputPressed(
                                    null, null, input, null, _mouseValue);
                                break;
                        }
                        continue;
                    }

                    // If it is a key release throw the key released event
                    if (WasButtonReleased(input))
                    {
                        _inputManager.InputReleased(
                            null, null, input, null, _mouseValue);
                        continue;
                    }

                    // If it is being held throw the key held event
                    if (WasButtonHeld(input))
                    {
                        _inputManager.InputHeld(
                            null, null, input, null, _mouseValue);
                        continue;
                    }
                }

                _LastMouseState = _CurrentMouseState;
            }

            /// <summary>
            /// Checks if the mouse Button passed in was pressed this frame
            /// </summary>
            /// <param name="mouseInput">the Button to test</param>
            /// <returns></returns>
            public bool WasButtonPressed(MouseClick mouseInput)
            {
                switch (mouseInput)
                {
                    case MouseClick.LEFT:
                        return (_CurrentMouseState.LeftButton
                                == ButtonState.Pressed) &&
                               (_LastMouseState.LeftButton
                                == ButtonState.Released);
                    case MouseClick.RIGHT:
                        return (_CurrentMouseState.RightButton
                                == ButtonState.Pressed) &&
                               (_LastMouseState.RightButton
                                == ButtonState.Released);
                    case MouseClick.MIDDLE:
                        return (_CurrentMouseState.MiddleButton
                                == ButtonState.Pressed) &&
                               (_LastMouseState.MiddleButton
                                == ButtonState.Released);
                    case MouseClick.BUTTON1:
                        return (_CurrentMouseState.XButton1
                                == ButtonState.Pressed) &&
                               (_LastMouseState.XButton1 == ButtonState.Released);
                    case MouseClick.BUTTON2:
                        return (_CurrentMouseState.XButton2
                                == ButtonState.Pressed) &&
                               (_LastMouseState.XButton2 == ButtonState.Released);
                    case MouseClick.MOVE:
                        return (_CurrentMouseState.X != _LastMouseState.X) ||
                               (_CurrentMouseState.Y != _LastMouseState.Y);
                    case MouseClick.SCROLL:
                        return (_CurrentMouseState.ScrollWheelValue
                                != _LastMouseState.ScrollWheelValue);
                    default:
                        return false;
                }
            }

            /// <summary>
            /// Checks if the mouse Button passed in was held this frame
            /// </summary>
            /// <param name="mouseInput">the Button to test</param>
            /// <returns></returns>
            public bool WasButtonHeld(MouseClick mouseInput)
            {
                switch (mouseInput)
                {
                    case MouseClick.LEFT:
                        return (_CurrentMouseState.LeftButton
                                == ButtonState.Pressed) &&
                               (_LastMouseState.LeftButton
                                == ButtonState.Pressed);
                    case MouseClick.RIGHT:
                        return (_CurrentMouseState.RightButton
                                == ButtonState.Pressed) &&
                               (_LastMouseState.RightButton
                                == ButtonState.Pressed);
                    case MouseClick.MIDDLE:
                        return (_CurrentMouseState.MiddleButton
                                == ButtonState.Pressed) &&
                               (_LastMouseState.MiddleButton
                                == ButtonState.Pressed);
                    case MouseClick.BUTTON1:
                        return (_CurrentMouseState.XButton1
                                == ButtonState.Pressed) &&
                               (_LastMouseState.XButton1 == ButtonState.Pressed);
                    case MouseClick.BUTTON2:
                        return (_CurrentMouseState.XButton2
                                == ButtonState.Pressed) &&
                               (_LastMouseState.XButton2 == ButtonState.Pressed);
                    default:
                        return false;
                }
            }

            /// <summary>
            /// Checks if the mouse Button passed in was released this frame
            /// </summary>
            /// <param name="mouseInput">the Button to test</param>
            /// <returns></returns>
            public bool WasButtonReleased(MouseClick mouseInput)
            {
                switch (mouseInput)
                {
                    case MouseClick.LEFT:
                        return (_CurrentMouseState.LeftButton
                                == ButtonState.Released) &&
                               (_LastMouseState.LeftButton
                                == ButtonState.Pressed);
                    case MouseClick.RIGHT:
                        return (_CurrentMouseState.RightButton
                                == ButtonState.Released) &&
                               (_LastMouseState.RightButton
                                == ButtonState.Pressed);
                    case MouseClick.MIDDLE:
                        return (_CurrentMouseState.MiddleButton
                                == ButtonState.Released) &&
                               (_LastMouseState.MiddleButton
                                == ButtonState.Pressed);
                    case MouseClick.BUTTON1:
                        return (_CurrentMouseState.XButton1
                                == ButtonState.Released) &&
                               (_LastMouseState.XButton1 == ButtonState.Pressed);
                    case MouseClick.BUTTON2:
                        return (_CurrentMouseState.XButton2
                                == ButtonState.Released) &&
                               (_LastMouseState.XButton2 == ButtonState.Pressed);
                    default:
                        return false;
                }
            }

            #endregion
        }

        #endregion
    }
}